package org.example.dev.learn.concurrency;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

public class Learn2CountDownLatch {
    public static void main(String[] args) throws InterruptedException {
        addNoConcurrency();
        addWithConcurrency();
        addWithReentrantLock();
    }


    /**
     * 起10个线程，每个线程加 1000 次，期望值是 10000，但因为并发，最后会小于 10000
     */
    public static void addNoConcurrency() throws InterruptedException {
        final int[] total = new int[1]; // 使用数组来模拟共享变量

        CountDownLatch downLatch = new CountDownLatch(1);
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    downLatch.await();
                    for (int j = 0; j < 1000; j++) {
                        total[0]++; // 非线程安全的增加操作
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        downLatch.countDown(); // 释放所有等待的线程
        Thread.sleep(2000); // 等待所有线程执行完成
        System.out.println(total[0]);
    }

    public static void addWithConcurrency() throws InterruptedException {
        AtomicInteger total = new AtomicInteger();
        CountDownLatch downLatch = new CountDownLatch(1);
        for(int i = 0; i < 10; i++){
            new Thread(() -> {
                try {
                    downLatch.await();
                    for(int j = 0; j < 1000; j++){
                        total.getAndIncrement();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        downLatch.countDown();
        Thread.sleep(2000);
        System.out.println(total.get());
    }

    public static void addWithReentrantLock() throws InterruptedException {
        CountDownLatch downLatch = new CountDownLatch(1);
        ReentrantLock lock = new ReentrantLock();
        final int[] total = new int[1];
        for(int i = 0; i < 10; i++){
            new Thread(() -> {
                lock.lock(); // 加锁
                try {
                    downLatch.await();
                    for(int j = 0; j < 1000; j++){
                        total[0]++;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock(); // 解锁
                }
            }).start();
        }
        downLatch.countDown();
        Thread.sleep(2000);
        System.out.println(total[0]);
    }
}
